/* Copyright (c) 2016-2020 Enfry Ltd. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Enfry. 
 * You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the agreements
 * you entered into with Enfry.
 */
package com.enfry.storage.common;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.enfry.storage.common.Constants;

public class StorageUtils {
    
    public static String getSecretUrl(String serverUrl, String apiName, String secret, Map<String, Object> param) throws IOException {
        String secretUrl = serverUrl + "/" + apiName;                                   // http://server/api
        String token = "?token=" + sign(apiName, secret, (long) param.get("ts"));       // 签名授权token
        
        // 参数拼接
        StringBuffer paramBuffer = new StringBuffer(token);
        Iterator<Entry<String, Object>> iterator = param.entrySet().iterator();
        while(iterator.hasNext()) {
            Entry<String, Object> entry = iterator.next();
            paramBuffer.append("&").append(entry.getKey()).append("=").append(entry.getValue());
        }
        return secretUrl + paramBuffer;
    }

    public static String sign(String apiName, String secret, long ts) throws IOException {
//        // 第一步：检查参数是否已经排序
//        String[] keys = params.keySet().toArray(new String[0]);
//        Arrays.sort(keys);
//
//        // 第二步：把所有参数名和参数值串在一起
//        StringBuilder query = new StringBuilder(secret);
//        for (String key : keys) {
//            String value = params.get(key);
//            if (StringUtils.areNotEmpty(key, value)) {
//                query.append(key).append(value);
//            }
//        }
//        String ts = params.get("ts");

        // 第三步：使用MD5加密
        byte[] bytes = encryptMD5(secret + apiName + ts);

        // 第四步：把二进制转化为大写的十六进制
        return byte2hex(bytes);
    }
    
    private static byte[] encryptMD5(String data) throws IOException {
        byte[] bytes = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            bytes = md.digest(data.getBytes(Constants.CHARSET_UTF8));
        } catch (GeneralSecurityException gse) {
            String msg = getStringFromException(gse);
            throw new IOException(msg);
        }
        return bytes;
    }
    
    private static String byte2hex(byte[] bytes) {
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toUpperCase());
        }
        return sign.toString();
    }
    
    private static String getStringFromException(Throwable e) {
        String result = "";
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(bos);
        e.printStackTrace(ps);
        try {
            result = bos.toString(Constants.CHARSET_UTF8);
        } catch (IOException ioe) {
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        String serverUrl = "http://192.168.0.20:8080/CEMSTORAGE";
        String appKey = "test";
        String appSecret = "098f6bcd4621d373cade4e832627b4f6"; 
        final String API_GET_FILE = "get.api";
        final String API_IMG_FILE = "img.api";
        final String API_UPLOAD_FILE = "upload.api";
        long ts = System.currentTimeMillis();
        
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("ts", ts);
        param.put("appKey", appKey);
        String uploadUrl = StorageUtils.getSecretUrl(serverUrl, API_UPLOAD_FILE, appSecret, param);
        
        String deleteUrl = StorageUtils.getSecretUrl(serverUrl, "delete.api", appSecret, param);
        
        param.put("fileCode", "3410ee9474e075bd274ffd4facd89d75.jpg");
        String viewUrl =  StorageUtils.getSecretUrl(serverUrl, API_GET_FILE, appSecret, param);
        String imgUrl =  StorageUtils.getSecretUrl(serverUrl, API_IMG_FILE, appSecret, param);

        System.out.println(viewUrl);
        System.out.println(imgUrl);
        System.out.println(uploadUrl);
        System.out.println(deleteUrl);
    }
}
